package net.xiduth.game.player.content.construction;

import java.util.ArrayList;
import java.util.List;

import net.xiduth.game.DynamicRegion;
import net.xiduth.game.Region;
import net.xiduth.game.RegionBuilder;
import net.xiduth.game.World;
import net.xiduth.game.WorldObject;
import net.xiduth.game.player.Player;
import net.xiduth.game.player.content.construction.Furniture.FurnitureObjects;

public class House {
	
	public static ArrayList<RoomReference> rooms;
	public ArrayList<WorldObject> objects;
	private byte place, look;

	
	public House() {		
		rooms = new ArrayList<RoomReference>();
		rooms.add(new RoomReference(Room.GARDEN, 4, 4, 0, 0));
		rooms.add(new RoomReference(Room.PARLOUR, 5, 4, 0, 0));
		rooms.add(new RoomReference(Room.GARDEN, 4, 4, 0, 0));
		place = 0;
		look = 5;
	}
	
	public static void makeChair(WorldObject o, Player player) {
		WorldObject object = null;
		object = new WorldObject(FurnitureObjects.CRUDECHAIR.getId(),
				o.getType(), o.getRotation(), o.getX(), o.getY(),
				o.getPlane());
		World.spawnObject(object, true);
	}

	
	public static void sendXMessage(Player player) {
		for(RoomReference reference : rooms) {
		player.out("Room X: "+ reference.room.chunkX + ", Room Y:" + reference.room.chunkY);
		}
	}
	
	public void addParlour(Player player, int[] boundChunks) {
		rooms.add(new RoomReference(Room.PARLOUR, 0, boundChunks[8], boundChunks[8], 0));
    	refresh(player, boundChunks);
	}
	
	public void refresh(Player player, int[] boundChuncks) {
		player.setForceNextMapLoadRefresh(true);
		constructHouse(boundChuncks, true, player);
		player.loadMapRegions();
	}
	public void initHouse(int[] boundChuncks, boolean buildMode) {
		Object[][][][] data = new Object[4][8][8][];
		for(RoomReference reference : rooms) {
			data[reference.plane][reference.x][reference.y] = 
				new Object[] {reference.room.chunkX,  reference.room.chunkY,
					reference.rotation, reference.room.showRoof};
		}
		if(!buildMode) { //construct roof
			for(int x = 1; x < 7; x++) {
				skipY: for(int y = 1; y < 7; y++) {
					for(int plane = 2; plane >= 0; plane--) {
						if(data[plane][x][y] != null) {
							boolean hasRoof = (boolean) data[plane][x][y][3];
							if(hasRoof) {
								byte rotation = (byte) data[plane][x][y][2];			
								//TODO find best Roof
								data[plane+1][x][y] = new Object[] {
										Roof.ROOF1.chunkX,
										Roof.ROOF1.chunkY, rotation, true};	
								continue skipY;
							}
						}
					}
				}
			}
		}
		for(int plane = 0; plane < data.length; plane++) {
			for(int x = 0; x < data[plane].length; x++) {
				for(int y = 0; y < data[plane][x].length; y++) {
					if(data[plane][x][y] != null) 
						RegionBuilder.copyChunk((int)data[plane][x][y][0] + 
								((boolean)data[plane][x][y][3] && look >= 4 ? 8 : 0)
								, (int)data[plane][x][y][1],
								(boolean)data[plane][x][y][3] ? look % 4 : place
								, boundChuncks[0]+x, boundChuncks[1]+y, plane,(byte)data[plane][x][y][2]);
					else if (plane == 0)
						RegionBuilder.copyChunk(LAND[0], LAND[1], place, boundChuncks[0]+x, boundChuncks[1]+y, plane, 0);
				}
			}
		}
		Region region = World.getRegion(RegionBuilder.getRegionHash(boundChuncks[0]/8, boundChuncks[1]/8));
		List<WorldObject> spawnedObjects = region.getSpawnedObjects();
		if(spawnedObjects != null)
			spawnedObjects.clear();
		List<WorldObject> removedObjects = region.getRemovedObjects();
		if(removedObjects != null)
			removedObjects.clear();
		for(RoomReference reference : rooms) {
			int boundX = reference.x * 8;
			int boundY = reference.y * 8;
			int chunkRotation = region.getRotation(reference.plane, boundX, boundY);
			for(int x = boundX; x < boundX+8; x++) {
				for(int y = boundY; y < boundY+8; y++) {
					WorldObject[] objects = region.getObjects(reference.plane, x, y);
					if(objects != null) {
						
						for(WorldObject object : objects) {
							if(!buildMode && object.getDefinitions().containsOption("Build")) {
								object = new WorldObject(object.getId(), object.getType(), (object.getRotation() + chunkRotation) % 4, x + boundChuncks[0]*8,y + boundChuncks[1]*8, reference.plane);
								World.removeObject(object, true);
							}else if (object.getDefinitions().name.equals("Window")) {
								object = new WorldObject(getWindowId(), object.getType(), (object.getRotation() + chunkRotation) % 4, x + boundChuncks[0]*8,y + boundChuncks[1]*8, reference.plane);
								World.spawnObject(object, false);
							}
						}
					}
				}
			}
		}
	}

	public void constructHouse(int[] boundChuncks, boolean buildMode, Player player) {
		Object[][][][] data = new Object[4][8][8][];
		for(RoomReference reference : rooms) {
			data[reference.plane][reference.x][reference.y] = 
				new Object[] {reference.room.chunkX,  reference.room.chunkY,
					reference.rotation, reference.room.showRoof};
		}
		if(!buildMode) { //construct roof
			for(int x = 1; x < 7; x++) {
				skipY: for(int y = 1; y < 7; y++) {
					for(int plane = 2; plane >= 0; plane--) {
						if(data[plane][x][y] != null) {
							boolean hasRoof = (boolean) data[plane][x][y][3];
							if(hasRoof) {
								byte rotation = (byte) data[plane][x][y][2];			
								//TODO find best Roof
								data[plane+1][x][y] = new Object[] {
										Roof.ROOF1.chunkX,
										Roof.ROOF1.chunkY, rotation, true};	
								continue skipY;
							}
						}
					}
				}
			}
		}
		for(int plane = 0; plane < data.length; plane++) {
			for(int x = 0; x < data[plane].length; x++) {
				for(int y = 0; y < data[plane][x].length; y++) {
					if(data[plane][x][y] != null) 
						RegionBuilder.copyChunk((int)data[plane][x][y][0] + 
								((boolean)data[plane][x][y][3] && look >= 4 ? 8 : 0)
								, (int)data[plane][x][y][1],
								(boolean)data[plane][x][y][3] ? look % 4 : place
								, boundChuncks[0]+x, boundChuncks[1]+y, plane,(byte)data[plane][x][y][2]);
					else if (plane == 0)
						RegionBuilder.copyChunk(LAND[0], LAND[1], place, boundChuncks[0]+x, boundChuncks[1]+y, plane, 0);
				}
			}
		}
		Region region = World.getRegion(RegionBuilder.getRegionHash(boundChuncks[0]/8, boundChuncks[1]/8));
		List<WorldObject> spawnedObjects = region.getSpawnedObjects();
		if(spawnedObjects != null)
			spawnedObjects.clear();
		List<WorldObject> removedObjects = region.getRemovedObjects();
		if(removedObjects != null)
			removedObjects.clear();
		for(RoomReference reference : rooms) {
			int boundX = reference.x * 8;
			int boundY = reference.y * 8;
			int chunkRotation = region.getRotation(reference.plane, boundX, boundY);
			for(int x = boundX; x < boundX+8; x++) {
				for(int y = boundY; y < boundY+8; y++) {
					WorldObject[] objects = region.getObjects(reference.plane, x, y);
					if(objects != null) {
						for(WorldObject object : objects) {
							if(!buildMode && object.getDefinitions().containsOption("Build")) {
								object = new WorldObject(object.getId(), object.getType(), (object.getRotation() + chunkRotation) % 4, x + boundChuncks[0]*8,y + boundChuncks[1]*8, reference.plane);
								World.removeObject(object, true);
								//World.removeObject(object, true);
								player.checkObjects(boundChuncks);
								
							} else if (object.getDefinitions().name.equals("Window")) {
								object = new WorldObject(getWindowId(), object.getType(), (object.getRotation() + chunkRotation) % 4, x + boundChuncks[0]*8,y + boundChuncks[1]*8, reference.plane);
								World.spawnObject(object, false);
							}
						}
					}
				}
			}
		}
	}
	
	public void previewRoom(Player player, int[] boundChuncks, RoomReference reference, boolean remove) {
		int boundX = reference.x * 8;
		int boundY = reference.y * 8;
		Region region = World.getRegion(RegionBuilder.getRegionHash(reference.room.chunkX/8, reference.room.chunkY/8));
		int boundX2 = (reference.room.chunkX - (reference.room.chunkX / 8 * 8)) * 8;
		int boundY2 = (reference.room.chunkY - (reference.room.chunkY / 8 * 8)) * 8;
		DynamicRegion house = (DynamicRegion) World.getRegion(RegionBuilder.getRegionHash(boundChuncks[0]/8, boundChuncks[1]/8));
		house.getRegionCoords()[reference.plane][reference.x][reference.y][3] = reference.rotation;
		for(int x = 0; x < 8; x++) {
			for(int y = 0; y < 8; y++) {
				WorldObject[] objects = region.getObjects(reference.plane, boundX2+x, boundY2+y);
				if(objects != null) {
					for(WorldObject object : objects) {
						if(object.getDefinitions().containsOption(2, "Build")) {
							int x2 = x;
							int y2 = y;
							for (int rotate = 0; rotate < reference.rotation; rotate++) {
								int fakeChunckX = x2;
								int fakeChunckY = y2;
								x2 = fakeChunckY;
								y2 = 7 - fakeChunckX;
							}
							object = new WorldObject(object.getId(), object.getType(), (object.getRotation() + reference.rotation) % 4, boundX + x2 + boundChuncks[0]*8, boundY + y2 + boundChuncks[1]*8, reference.plane);
							if(remove)
								player.getPackets().sendDestroyObject(object);
							else
								player.getPackets().sendSpawnedObject(object);
						}
					}
				}
			}
		}
	}
	
	public int getWindowId() {
		switch(look) {
		default:
			return 13117;
		}
	}
	private static final int[] LAND = {233, 632};
	
	public static enum Room {
		GARDEN(232, 633, false, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.WEST),
		PARLOUR(232, 639, false, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.WEST),
		BEDROOM(238, 639, false, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.WEST),
		DININGROOM(236, 639, false, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.WEST),
		WorkShop(232, 637, false, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.WEST),
		Portal(233, 636, false, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.WEST),
		KITCHEN(234, 639, false, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.WEST),
		FGarden(234, 633, false, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.WEST),
		BOXING(235, 636, false, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.WEST),
		Throne(238, 637, false, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.WEST),
		Study(236, 637, false, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.WEST),
		QuestHall(239, 638, false, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.WEST),
		Chapel(234, 637, false, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.WEST);

		private int chunkX, chunkY;
		private boolean showRoof;
		private int[] doorDirs;
		private Room(int chunkX, int chunkY, boolean showRoof, int... doorDirs) {
			this.chunkX = chunkX;
			this.chunkY = chunkY;
			this.showRoof = showRoof;
			this.doorDirs = doorDirs;
		}
	}
	
	public static void openInter(Player player) {
		player.getInterfaceManager().sendInterface(402);
	}
	
	public static void openBench(Player player) {
		player.getInterfaceManager().sendInterface(397);
	}


	public static enum Roof {
		
		ROOF1(233, 634, RegionBuilder.NORTH, RegionBuilder.SOUTH),
		ROOF2(235, 634, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH),
		ROOF3(235, 634, RegionBuilder.NORTH, RegionBuilder.EAST, RegionBuilder.SOUTH, RegionBuilder.NORTH);
		
		private int chunkX, chunkY;
		private int[] dirs;
		
		private Roof(int chunkX, int chunkY, int... dirs) {
			this.chunkX = chunkX;
			this.chunkY = chunkY;
			this.dirs = dirs;
		}
	}
	
	public static class RoomReference {
		
		public RoomReference(Room room, int x, int y, int plane, int rotation) {
			this.room = room;
			this.x = (byte) x;
			this.y = (byte) y;
			this.plane = (byte) plane;
			this.rotation = (byte) rotation;
		}
		private Room room;
		private byte x, y, plane, rotation;
		
	}
}
